package com.gree.yipai.base;


import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Message;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.PopupWindow;

import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.core.app.ActivityOptionsCompat;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner;

import com.githang.statusbar.StatusBarCompat;
import com.gree.yipai.Const;
import com.gree.yipai.R;
import com.gree.yipai.base.basemodel.BaseViewModel;
import com.gree.yipai.base.callback.IView;
import com.gree.yipai.base.livedata.MessageEvent;
import com.gree.yipai.base.livedata.StatusEvent;
import com.gree.yipai.base.navigator.BaseNavigator;
import com.gree.yipai.databinding.ActivityBasePageLightBinding;
import com.gree.yipai.dialog.BaseProgressDialog;
import com.gree.yipai.utils.AnimatorUtil;
import com.gree.yipai.utils.CommonUtil;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import timber.log.Timber;


/**
 * Create by 游德禄 on 2019-9-3
 * 子页面基础页
 */
public abstract class BasePageLightActivity<VM extends BaseViewModel,VDB
        extends ViewDataBinding> extends BaseActivity implements IView<VM>, BaseNavigator {
    private View.OnClickListener onClickListener;
    private int statusColor = 0 ;
    private boolean statusLight ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(setStatusBar()) {
            setStatusBar(R.color.white, true);
        }
        initView();
    }

    public void setContentViewRes(int layoutResID) {
        View view = LayoutInflater.from(this).inflate(layoutResID, null);
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 1);
        baseBinding.layoutContainer.addView(view, lp);
        mBinding = DataBindingUtil.bind(view);
    }
    private void initView(){
        baseBinding = DataBindingUtil.setContentView(this, R.layout.activity_base_page_light);
        onClickListener = view -> {
            switch (view.getId()){
                case R.id.leftBtn:
                    if(onFinish()){
                        finish();
                    }
                    break;
                case R.id.rightBtn:
                    onRightBtnClick(baseBinding.rightBtn);
                    break;
            }
        };
        baseBinding.leftBtn.setOnClickListener(onClickListener);
        baseBinding.rightBtn.setOnClickListener(onClickListener);
    }

    /**
     * 设置状态栏颜色
     * @param color
     * @param light
     */
    public void setStatusBar(int color,boolean light){
        statusColor = color ;
        statusLight = light;
        StatusBar(color,light);
    }

    /**
     *  设置状态栏透明
     */
    public void statusBarTranslucent(){
        StatusBarCompat.setTranslucent(getWindow(),true);
    }
    protected void StatusBar(int color,boolean light){
        StatusBarCompat.setStatusBarColor(this, getResources().getColor(color), light);
    }
    public abstract boolean setStatusBar();


    /**
     * 设置标题
     * @param title
     */
    public void setTitle(String title){
        baseBinding.title.setText(title);
    }

    /**
     * 设置左边按钮文字
     * @param text
     */
    public void setLeftText(String text){
        baseBinding.leftText.setVisibility(View.VISIBLE);
        baseBinding.leftText.setText(text);
    }
    /**
     * 设置右边按钮文字
     * @param text
     */
    public void setRightText(String text){
        baseBinding.rightText.setVisibility(View.VISIBLE);
        baseBinding.rightText.setText(text);
    }

    /**
     * 设置左边按钮图标
     * @param r
     */
    public void setLeftImg(int r){
        baseBinding.leftImg.setImageResource(r);
    }

    /**
     * 设置右边按钮图标
     * @param r
     */
    public void setRightImg(int r){
        baseBinding.rightImg.setImageResource(r);
    }

    /**
     * 隐藏左边按钮
     */
    public void hideLeftBtn(){
        baseBinding.leftBtn.setVisibility(View.GONE);
    }

    /**
     * 隐藏右边按钮
     */
    public void hideRightBtn(){
        baseBinding.rightBtn.setVisibility(View.GONE);
    }

    /**
     * 隐藏标题栏
     */
    public void hideHeader(){
        baseBinding.header.setVisibility(View.GONE);
    }
    /**
     * 设置标题栏背景
     * @param r
     */
    public void setHeaderBg(int r){
        baseBinding.header.setBackgroundResource(r);
    }

    /**
     * 由子类决定是否关闭页面
     * @return
     */
    public abstract boolean onFinish();

    /**
     * 右边按钮点击
     * @return
     */
    public abstract void onRightBtnClick(View view);


    /**
     * 显示提示
     * @param msg
     */
    public void showMsgOk(String msg){
        showMessage(msg,3000, R.mipmap.icon_ok, R.color.msg_ok);
    }
    public void showMsgErr(String msg){
        showMessage(msg,3000, R.mipmap.icon_error, R.color.msg_err);
    }
    public void showMsgWarn(String msg){
        showMessage(msg,3000, R.mipmap.icon_warn, R.color.msg_warn);
    }
    public void showMsgOk(String msg,int time){
        showMessage(msg,time, R.mipmap.icon_ok, R.color.msg_ok);
    }
    public void showMsgErr(String msg,int time){
        showMessage(msg,time, R.mipmap.icon_error, R.color.msg_err);
    }
    public void showMsgWarn(String msg,int time){
        showMessage(msg,time, R.mipmap.icon_warn, R.color.msg_warn);
    }

    /**
     * 显示提示
     * @param msg
     * @param time
     */
    public void showMessage(String msg,final int time,int r,final int color){
        if(baseBinding.msgBox.getVisibility()==View.VISIBLE){
            return;
        }
        if(Const.DEBUG){
            if(msg.contains("#")){
                //NLog.e("showToast",msg);
                shortToast("服务端异常信息:"+msg.substring(msg.indexOf("#")+1,msg.length()));
                msg = msg.substring(0,msg.indexOf("#"));
            }
        }
        baseBinding.msgText.setText(msg);
        baseBinding.msgBox.setBackgroundColor(getResources().getColor(color));
        if(r!=0) {
            if(baseBinding.msgImg.getVisibility()!=View.VISIBLE) {
                baseBinding.msgImg.setVisibility(View.VISIBLE);
            }
            baseBinding.msgImg.setImageResource(r);
        }else{
            baseBinding.msgImg.setVisibility(View.GONE);
        }
        baseBinding.msgBox.post(new Runnable() {
            @Override
            public void run() {
                if(isTransparentBar()) {
                    baseBinding.msgBox.setPadding(0, CommonUtil.getStatusBarHeight(mContext),0,0);
                }else{
                    StatusBar(color, false);
                }
                AnimatorUtil.animOpen(baseBinding.msgBox);
                if(time>0){
                    baseBinding.msgBox.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            hideMessage();
                        }
                    }, time);
                }
            }
        });
    }
    //判断是否是全屏
    private boolean isTransparentBar(){
        return (getWindow().getStatusBarColor()==Color.TRANSPARENT);
    }
    public void hideMessage(){
        AnimatorUtil.animClose(baseBinding.msgBox);
        if(!isTransparentBar()) {
            baseBinding.msgBox.postDelayed(new Runnable() {
                @Override
                public void run() {
                    StatusBar(statusColor, statusLight);
                }
            }, 500);
        }
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        destroy();
    }



    /**
     * 请通过 {@link #getViewModel()}获取，后续版本 {@link #mViewModel}可能会私有化
     */
    private VM mViewModel;

    /**
     * 请通过 {@link #getViewDataBinding()}获取，后续版本 {@link #mBinding}可能会私有化
     */
    protected ActivityBasePageLightBinding baseBinding;
    private VDB mBinding;
    protected static final float DEFAULT_WIDTH_RATIO = 0.85f;
    private Dialog mDialog;
    private Dialog mProgressDialog;
    private String mJumpTag;
    private long mJumpTime;
    private static final long IGNORE_INTERVAL_TIME = 500;

    /**
     * 销毁
     */
    private void destroy(){
        if(mViewModel != null){
            getLifecycle().removeObserver(mViewModel);
            mViewModel = null;
        }

        if(mBinding != null){
            mBinding.unbind();
        }
    }
    /**
     * 初始化 {@link #mViewModel}
     */
    private void initViewModel(){
        mViewModel = createViewModel();
        if(mViewModel != null){
            getLifecycle().addObserver(mViewModel);
            registerLoadingEvent();
        }
    }

    private Class<VM> getVMClass(){
        Class cls = getClass();
        Class<VM> vmClass = null;
        while (vmClass == null && cls!= null){
            vmClass = getVMClass(cls);
            cls = cls.getSuperclass();
        }
        if(vmClass == null){
            vmClass = (Class<VM>) BaseViewModel.class;
        }
        return vmClass;
    }

    private Class getVMClass(Class cls){
        Type type = cls.getGenericSuperclass();
        if(type instanceof ParameterizedType){
            Type[] types = ((ParameterizedType)type).getActualTypeArguments();
            for(Type t : types){
                if(t instanceof Class){
                    Class vmClass = (Class)t;
                    if(BaseViewModel.class.isAssignableFrom(vmClass)){
                        return vmClass;
                    }
                }else if(t instanceof ParameterizedType){
                    Type rawType = ((ParameterizedType)t).getRawType();
                    if(rawType instanceof Class){
                        Class vmClass = (Class)rawType;
                        if(BaseViewModel.class.isAssignableFrom(vmClass)){
                            return vmClass;
                        }
                    }
                }
            }
        }
        return null;
    }


    /**
     * 注册状态加载事件
     */
    protected void registerLoadingEvent(){
        mViewModel.getLoadingEvent().observe(this, (Observer<Boolean>) isLoading -> {
            if(isLoading != null && isLoading){
                showLoading();
            }else{
                hideLoading();
            }
        });
    }

    @Override
    public void showLoading() {
        showProgressDialog();
    }

    @Override
    public void hideLoading() {
        dismissProgressDialog();
    }

    /**
     * 注册消息事件
     */
    protected void registerMessageEvent(@NonNull MessageEvent.MessageObserver observer){
        getViewModel().getMessageEvent().observe(this,observer);
    }

    /**
     * 注册单个消息事件，消息对象:{@link Message}
     * @param observer
     */
    protected void registerSingleLiveEvent(@NonNull Observer<Message> observer){
        getViewModel().getSingleLiveEvent().observe(this,observer);
    }

    /**
     * 注册状态事件
     * @param observer
     */
    protected void registerStatusEvent(@NonNull StatusEvent.StatusObserver observer){
        getViewModel().getStatusEvent().observe(this,observer);
    }

    public Context getContext(){
        return this;
    }

    /**
     * 创建ViewModel
     * @return {@link #mViewModel}会默认根据当前Activity泛型 {@link VM}获得ViewModel
     */
    @Override
    public VM createViewModel(){
        return obtainViewModel(getVMClass());
    }

    /**
     * 获取 ViewModel
     * @return {@link #mViewModel}
     */
    public VM getViewModel(){
        return mViewModel;
    }

    /**
     * 获取 ViewDataBinding
     * @return {@link #mBinding}
     */
    public VDB getViewDataBinding(){
        return mBinding;
    }

    /**
     * 同 {@link #getViewDataBinding()}
     * @return {@link #mBinding}
     */
    public VDB getBinding(){
        return mBinding;
    }


    /**
     * 通过 {@link #createViewModelProvider(ViewModelStoreOwner)}获得 ViewModel
     * @param modelClass
     * @param <T>
     * @return
     */
    public <T extends ViewModel> T obtainViewModel(@NonNull Class<T> modelClass){
        return createViewModelProvider(this).get(modelClass);
    }

    /**
     * @deprecated 请使用 {@link #obtainViewModel(Class)}
     * @param modelClass
     * @param <T>
     * @return
     */
    @Deprecated
    public <T extends ViewModel> T getViewModel(@NonNull Class<T> modelClass){
        return obtainViewModel(modelClass);
    }

    /**
     * 创建 {@link ViewModelProvider}
     * @param owner
     * @return
     */
    private ViewModelProvider createViewModelProvider(@NonNull ViewModelStoreOwner owner){
        return new ViewModelProvider(owner);
    }

    //---------------------------------------

    protected Intent newIntent(Class<?> cls){
        return new Intent(getContext(),cls);
    }

    protected Intent newIntent(Class<?> cls,int flags){
        Intent intent = newIntent(cls);
        intent.addFlags(flags);
        return intent;
    }

    protected void startActivity(Class<?> cls){
        startActivity(newIntent(cls));
    }

    protected void startActivity(Class<?> cls,int flags){
        startActivity(newIntent(cls,flags));
    }

    protected void startActivity(Class<?> cls,@Nullable ActivityOptionsCompat optionsCompat){
        startActivity(newIntent(cls),optionsCompat);
    }

    protected void startActivity(Class<?> cls, int flags, @Nullable ActivityOptionsCompat optionsCompat){
        startActivity(newIntent(cls,flags),optionsCompat);
    }

    protected void startActivity(Intent intent, @Nullable ActivityOptionsCompat optionsCompat){
        if(optionsCompat != null&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN){
            startActivity(intent,optionsCompat.toBundle());
        }else{
            startActivity(intent);
        }
    }

    protected void startActivityFinish(Class<?> cls){
        startActivity(cls);
        finish();
    }

    protected void startActivityFinish(Class<?> cls,int flags){
        startActivity(cls,flags);
        finish();
    }

    protected void startActivityFinish(Class<?> cls,@Nullable ActivityOptionsCompat optionsCompat){
        startActivity(cls,optionsCompat);
        finish();
    }

    protected void startActivityFinish(Class<?> cls,int flags,@Nullable ActivityOptionsCompat optionsCompat){
        startActivity(newIntent(cls,flags),optionsCompat);
    }

    protected void startActivityFinish(Intent intent,@Nullable ActivityOptionsCompat optionsCompat){
        startActivity(intent,optionsCompat);
    }

    protected void startActivityForResult(Class<?> cls,int requestCode){
        startActivityForResult(newIntent(cls),requestCode);
    }

    protected void startActivityForResult(Class<?> cls,int requestCode,@Nullable ActivityOptionsCompat optionsCompat){
        Intent intent = newIntent(cls);
        if(optionsCompat != null){
            startActivityForResult(intent,requestCode,optionsCompat.toBundle());
        }else{
            startActivityForResult(intent,requestCode);
        }
    }

    @Override
    public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if(isIgnoreJump(intent)){
            return;
        }
        super.startActivityForResult(intent, requestCode, options);
    }

    protected boolean isIgnoreJump(Intent intent){
        String jumpTag;
        if(intent.getComponent() != null){
            jumpTag = intent.getComponent().getClassName();
        }else if(intent.getAction() != null){
            jumpTag = intent.getAction();
        }else{
            return false;
        }

        if(TextUtils.isEmpty(jumpTag)){
            return false;
        }

        if(jumpTag.equals(mJumpTag) && mJumpTime > SystemClock.elapsedRealtime() - getIgnoreIntervalTime()){
            Timber.d("Ignore:" + jumpTag);
            return true;
        }
        mJumpTag = jumpTag;
        mJumpTime = SystemClock.elapsedRealtime();

        return false;
    }

    protected long getIgnoreIntervalTime(){
        return IGNORE_INTERVAL_TIME;
    }

    //---------------------------------------

    protected View inflate(@LayoutRes int id){
        return inflate(id,null);
    }

    protected View inflate(@LayoutRes int id,@Nullable ViewGroup root){
        return LayoutInflater.from(getContext()).inflate(id,root);
    }

    protected View inflate(@LayoutRes int id,@Nullable ViewGroup root, boolean attachToRoot){
        return LayoutInflater.from(getContext()).inflate(id,root,attachToRoot);
    }

    //---------------------------------------

    protected void showDialogFragment(DialogFragment dialogFragment){
        String tag = dialogFragment.getTag() !=null ? dialogFragment.getTag() : dialogFragment.getClass().getSimpleName();
        showDialogFragment(dialogFragment,tag);
    }

    protected void showDialogFragment(DialogFragment dialogFragment, String tag) {
        dialogFragment.show(getSupportFragmentManager(),tag);
    }

    protected void showDialogFragment(DialogFragment dialogFragment, FragmentManager fragmentManager, String tag) {
        dialogFragment.show(fragmentManager,tag);
    }

    private View.OnClickListener mOnDialogCancelClick = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            dismissDialog();

        }
    };

    protected Dialog getDialog(){
        return this.mDialog;
    }

    protected Dialog getProgressDialog(){
        return this.mProgressDialog;
    }

    protected View.OnClickListener getDialogCancelClick(){
        return mOnDialogCancelClick;
    }

    protected void dismissDialog(){
        dismissDialog(mDialog);
    }

    protected void dismissDialog(Dialog dialog){
        if(dialog != null && dialog.isShowing()){
            dialog.dismiss();
        }
    }

    protected void dismissPopupWindow(PopupWindow popupWindow){
        if(popupWindow!=null && popupWindow.isShowing()){
            popupWindow.dismiss();
        }
    }

    protected void dismissProgressDialog(){
        dismissDialog(mProgressDialog);
    }

    protected void showProgressDialog(){
        showProgressDialog(false);
    }

    protected void showProgressDialog(boolean isCancel){
        showProgressDialog(R.layout.dialog_progress,isCancel);
    }

    protected void showProgressDialog(@LayoutRes int resId){
        showProgressDialog(resId,false);
    }

    protected void showProgressDialog(@LayoutRes int resId, boolean isCancel){
        showProgressDialog(inflate(resId),isCancel);
    }

    protected void showProgressDialog(View v){
        showProgressDialog(v,false);
    }

    protected void showProgressDialog(View v,boolean isCancel){
        dismissProgressDialog();
        mProgressDialog =  BaseProgressDialog.newInstance(getContext());
        mProgressDialog.setContentView(v);
        mProgressDialog.setCanceledOnTouchOutside(isCancel);
        mProgressDialog.show();
    }

    protected void showDialog(View contentView){
        showDialog(contentView,DEFAULT_WIDTH_RATIO);
    }

    protected void showDialog(View contentView,boolean isCancel){
        showDialog(getContext(),contentView, R.style.app_dialog,DEFAULT_WIDTH_RATIO,isCancel);
    }

    protected void showDialog(View contentView,float widthRatio){
        showDialog(getContext(),contentView,widthRatio);
    }

    protected void showDialog(View contentView,float widthRatio,boolean isCancel){
        showDialog(getContext(),contentView, R.style.app_dialog,widthRatio,isCancel);
    }

    protected void showDialog(Context context,View contentView,float widthRatio){
        showDialog(context,contentView, R.style.app_dialog,widthRatio);
    }

    protected void showDialog(Context context, View contentView, @StyleRes int resId, float widthRatio){
        showDialog(context,contentView,resId,widthRatio,true);
    }

    protected void showDialog(Context context, View contentView, @StyleRes int resId, float widthRatio, final boolean isCancel){
        dismissDialog();
        mDialog = new Dialog(context,resId);
        mDialog.setContentView(contentView);
        mDialog.setCanceledOnTouchOutside(false);
        mDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
            @Override
            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
                if(keyCode == KeyEvent.KEYCODE_BACK){
                    if(isCancel){
                        dismissDialog();
                    }
                    return true;
                }
                return false;

            }
        });
        setDialogWindow(mDialog,widthRatio);
        mDialog.show();

    }

    protected void setDialogWindow(Dialog dialog, float widthRatio){
        setWindow(dialog.getWindow(),widthRatio);
    }

    protected void setWindow(Window window, float widthRatio){
        WindowManager.LayoutParams lp = window.getAttributes();
        lp.width = (int)(getWidthPixels() * widthRatio);
        window.setAttributes(lp);
    }

    //---------------------------------------

    protected DisplayMetrics getDisplayMetrics(){
        return getResources().getDisplayMetrics();
    }

    protected int getWidthPixels(){
        return getDisplayMetrics().widthPixels;
    }

    protected int getHeightPixels(){
        return getDisplayMetrics().heightPixels;
    }
}
